﻿using System.Linq.Expressions;
using SqlSugar;
using WeDonekRpc.Helper;
using WeDonekRpc.Model;

namespace WeDonekRpc.SqlSugar
{
    public static class AsyncRepository
    {
        public static async Task<bool> AddOrUpdateAsync<T> ( this IRepository<T> repository, List<T> datas ) where T : class, new()
        {
            return await repository.Provider.Storageable(datas).ExecuteCommandAsync() > 0;
        }

        public static Task<bool> AddOrUpdateAsync<T> ( this IRepository<T> repository, List<T> datas, Expression<Func<T, object>> filter ) where T : class, new()
        {
            return Task.Factory.StartNew(() =>
            {
                return repository.AddOrUpdate(datas, filter);
            });
        }

        public static Task<bool> AddOrUpdateAsync<T> ( this IRepository<T> repository, List<T> datas, string table, Expression<Func<T, object>> filter ) where T : class, new()
        {
            return Task.Factory.StartNew(() =>
            {
                return repository.AddOrUpdate(datas, table, filter);
            });
        }

        public static async Task<bool> AddOrUpdateAsync<T> ( this IRepository<T> repository, List<T> datas, Func<StorageableInfo<T>, bool> insert, Func<StorageableInfo<T>, bool> update ) where T : class, new()
        {
            return await repository.Provider.Storageable(datas).SplitInsert(insert).SplitUpdate(update).ExecuteCommandAsync() > 0;
        }

        public static Task<bool> AddOrUpdateAsync<T> ( this IRepository<T> repository, List<T> datas, Expression<Func<T, object>> filter, Expression<Func<T, object>> update ) where T : class, new()
        {
            return Task.Factory.StartNew(() =>
            {
                return repository.AddOrUpdate(datas, filter, update);
            });
        }

        public static Task<Result> AvgAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.Where(filter).AvgAsync(selector);
        }
        public static Task<Result> AvgAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.AvgAsync(selector);
        }
        public static Task<int> CountAsync<T> ( this IRepository<T> repository ) where T : class, new()
        {
            return repository.Queryable.CountAsync();
        }
        public static Task<int> CountAsync<T> ( this IRepository<T> repository, Expression<Func<T, bool>> filter ) where T : class, new()
        {
            return repository.Queryable.Where(filter).CountAsync();
        }
        public static Task<int> CountAsync<T> ( this IRepository<T> repository, string table, Expression<Func<T, bool>> filter ) where T : class, new()
        {
            return repository.Queryable.Where(filter).AS(table).CountAsync();
        }

        public static Task<bool> DeleteAsync<T> ( this IRepository repository, T data ) where T : class, new()
        {
            return repository.Provider.Deleteable(data).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> DeleteAsync<T> ( this IRepository repository, Expression<Func<T, bool>> filter ) where T : class, new()
        {
            return repository.Provider.Deleteable<T>().Where(filter).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> DeleteAsync<T> ( this IRepository repository, Expression<Func<T, bool>> filter, Expression<Func<T, object>> selector, int num ) where T : class, new()
        {
            return repository.Provider.Deleteable<T>().In(selector, repository.Provider.Queryable<T>().Where(filter).Take(num).Select(selector)).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> DeleteAsync<T, Other> ( this IRepository repository, Expression<Func<T, Other, bool>> filter ) where Other : class, new() where T : class, new()
        {
            return repository.Provider.Deleteable<T>().Where(p => SqlFunc.Subqueryable<Other>().Where(filter).Any()).ExecuteCommandHasChangeAsync();
        }

        public static Task<bool> DeleteByKeyAsync<T, IdentityId> ( this IRepository repository, IdentityId id ) where T : class, new()
        {
            return repository.Provider.Deleteable<T>().In(id).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> DeleteByKeyAsync<T, IdentityId> ( this IRepository repository, IdentityId[] ids ) where T : class, new()
        {
            return repository.Provider.Deleteable<T>().In(ids).ExecuteCommandHasChangeAsync();
        }

        public static Task<int> ExecuteSqlAsync ( this IRepository repository, string sql, params SugarParameter[] param )
        {
            return repository.Provider.Ado.ExecuteCommandAsync(sql, param);
        }

        public static Task<Result> GetAsync<Result> ( this IRepository repository, ISugarQueryable<Result>[] list, string orderBy ) where Result : class, new()
        {
            return repository.Provider.UnionAll(list).OrderBy(orderBy).FirstAsync();
        }

        public static Task<Result> GetAsync<Table, Result> ( this IRepository repository, ISugarQueryable<Table>[] list, Expression<Func<Table, Result>> selector, string orderBy ) where Table : class, new()
        {
            return repository.Provider.UnionAll(list).OrderBy(orderBy).Select(selector).FirstAsync();
        }

        public static Task<T> GetAsync<T> ( this IRepository<T> repository, Expression<Func<T, bool>> filter ) where T : class, new()
        {
            return repository.Queryable.Where(filter).FirstAsync();
        }
        public static Task<T> GetAsync<T> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, string orderby ) where T : class, new()
        {
            return repository.Queryable.Where(filter).OrderBy(orderby).FirstAsync();
        }
        public static Task<Result> GetAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, Result>> selector, string orderby ) where T : class, new()
        {
            return repository.Queryable.OrderBy(orderby).Select(selector).FirstAsync();
        }

        public static Task<Result> ExecuteSqlAsync<Result> ( this IRepository repository, string sql, params SugarParameter[] param ) where Result : class
        {
            return repository.Provider.Ado.SqlQuerySingleAsync<Result>(sql, param);
        }
        public static Task<Result> GetAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.Where(filter).Select(selector).FirstAsync();
        }
        public static Task<Result> GetAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter ) where T : class, new() where Result : class
        {
            return repository.Queryable.Where(filter).Select<Result>().FirstAsync();
        }
        public static Task<Result> GetAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, Result>> selector, string orderby ) where T : class, new()
        {
            return repository.Queryable.Where(filter).OrderBy(orderby).Select(selector).FirstAsync();
        }

        public static Task<T[]> GetAllAsync<T> ( this IRepository<T> repository ) where T : class, new()
        {
            return repository.Queryable.ToArrayAsync();
        }
        public static Task<Result[]> GetAllAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.Select<Result>().ToArrayAsync();
        }
        public static Task<Result[]> GetAllAsync<T, Result> ( this IRepository<T> repository ) where T : class, new() where Result : class
        {
            return repository.Queryable.Select<Result>().ToArrayAsync();
        }
        public static Task<Result[]> GetAllAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, Result>> selector, string orderby ) where T : class, new()
        {
            return repository.Queryable.OrderBy(orderby).Select<Result>().ToArrayAsync();
        }
        public static Task<Result[]> GetAllAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, Result>> selector, Expression<Func<T, object>> orderBy, OrderByType type = OrderByType.Asc ) where T : class, new()
        {
            return repository.Queryable.OrderBy(orderBy, type).Select(selector).ToArrayAsync();
        }

        public static Task<T> GetByIdAsync<T, IdentityId> ( this IRepository<T> repository, IdentityId id ) where T : class, new()
        {
            return repository.Queryable.In(id).FirstAsync();
        }

        public static Task<Result> GetByIdAsync<T, IdentityId, Result> ( this IRepository<T> repository, IdentityId id ) where T : class, new() where Result : class
        {
            return repository.Queryable.In(id).Select<Result>().FirstAsync();
        }
        public static Task<Result> GetByIdAsync<T, IdentityId, Result> ( this IRepository<T> repository, IdentityId id, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.In(id).Select(selector).FirstAsync();
        }
        public static Task<Result[]> GetsAsync<T, Table, Result> ( this IRepository<T> repository, Expression<Func<T, Result>> selector, IBasicPage paging ) where T : class, new()
        {
            if ( paging.OrderBy.IsNull() )
            {
                return repository.Queryable.Select(selector).Skip(( paging.Index - 1 ) * paging.Size).Take(paging.Size).ToArrayAsync();
            }
            return repository.Queryable.OrderBy(paging.OrderBy).Select(selector).Skip(( paging.Index - 1 ) * paging.Size).Take(paging.Size).ToArrayAsync();
        }

        public static Task<Table[]> GetsAsync<Table> ( this IRepository repository, ISugarQueryable<Table>[] list, string orderBy ) where Table : class, new()
        {
            return repository.Provider.UnionAll(list).OrderBy(orderBy).ToArrayAsync();
        }
        public static Task<Result[]> GetsAsync<Result> ( this IRepository repository, ISugarQueryable<Result>[] list ) where Result : class
        {
            return repository.Provider.UnionAll(list).ToArrayAsync();
        }
        public static Task<Result[]> GetsAsync<Table, Result> ( this IRepository repository, ISugarQueryable<Table>[] list, Expression<Func<Table, Result>> selector, string orderBy ) where Table : class, new()
        {
            return repository.Provider.UnionAll(list).OrderBy(orderBy).Select(selector).ToArrayAsync();
        }
        public static Task<Result[]> GetsAsync<Table, Result> ( this IRepository repository, ISugarQueryable<Table>[] list ) where Table : class, new() where Result : class
        {
            return repository.Provider.UnionAll(list).Select<Result>().ToArrayAsync();
        }
        public static Task<Result[]> GetsAsync<Table, Result> ( this IRepository repository, ISugarQueryable<Table>[] list, Expression<Func<Table, Result>> selector ) where Table : class, new()
        {
            return repository.Provider.UnionAll(list).Select(selector).ToArrayAsync();
        }

        public static Task<T[]> GetsAsync<T> ( this IRepository<T> repository, Expression<Func<T, bool>> filter ) where T : class, new()
        {
            return repository.Queryable.Where(filter).ToArrayAsync();
        }
        public static Task<T[]> GetsAsync<T> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, string orderby ) where T : class, new()
        {
            return repository.Queryable.Where(filter).OrderBy(orderby).ToArrayAsync();
        }
        public static Task<T[]> GetsAsync<T> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, object>> orderBy, OrderByType type = OrderByType.Asc ) where T : class, new()
        {
            return repository.Queryable.Where(filter).OrderBy(orderBy, type).ToArrayAsync();
        }
        public static Task<Result[]> GetsAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter ) where T : class, new() where Result : class
        {
            return repository.Queryable.Where(filter).Select<Result>().ToArrayAsync();
        }
        public static Task<Result[]> GetsAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.Where(filter).Select(selector).ToArrayAsync();
        }
        public static Task<Result[]> GetsAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, Result>> selector, string orderby ) where T : class, new()
        {
            return repository.Queryable.Where(filter).OrderBy(orderby).Select(selector).ToArrayAsync();
        }
        public static Task<Result[]> GetsAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, Result>> selector, Expression<Func<T, object>> orderBy, OrderByType type = OrderByType.Asc ) where T : class, new()
        {
            return repository.Queryable.Where(filter).OrderBy(orderBy, type).Select(selector).ToArrayAsync();
        }
        public static Task<Result[]> GetsAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, string orderby ) where T : class, new() where Result : class
        {
            return repository.Queryable.Where(filter).OrderBy(orderby).Select<Result>().ToArrayAsync();
        }
        public static Task<Result[]> GetsAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, object>> orderBy, OrderByType type = OrderByType.Asc ) where T : class, new() where Result : class
        {
            return repository.Queryable.Where(filter).OrderBy(orderBy, type).Select<Result>().ToArrayAsync();
        }
        public static Task<List<Result>> GetsAsync<Result> ( this IRepository repository, string sql, params SugarParameter[] param )
        {
            return repository.Provider.Ado.SqlQueryAsync<Result>(sql, param);
        }
        public static Task<T[]> GetsByIdAsync<T, IdentityId> ( this IRepository<T> repository, IdentityId[] ids ) where T : class, new()
        {
            return repository.Queryable.In(ids).ToArrayAsync();
        }
        public static Task<Result[]> GetsByIdAsync<T, IdentityId, Result> ( this IRepository<T> repository, IdentityId[] ids ) where T : class, new() where Result : class
        {
            return repository.Queryable.In(ids).Select<Result>().ToArrayAsync();
        }
        public static Task<Result[]> GetsByIdAsync<T, IdentityId, Result> ( this IRepository<T> repository, IdentityId[] ids, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.In(ids).Select(selector).ToArrayAsync();
        }
        public static Task<Result[]> GetsByIdAsync<T, IdentityId, Result> ( this IRepository<T> repository, IdentityId[] ids, Expression<Func<T, Result>> selector, string orderBy ) where T : class, new()
        {
            return repository.Queryable.In(ids).OrderBy(orderBy).Select(selector).ToArrayAsync();
        }
        public static Task<Result[]> GetsByIdAsync<T, IdentityId, Result> ( this IRepository<T> repository, IdentityId[] ids, Expression<Func<T, Result>> selector, Expression<Func<T, object>> orderBy, OrderByType type = OrderByType.Asc ) where T : class, new()
        {
            return repository.Queryable.In(ids).OrderBy(orderBy, type).Select(selector).ToArrayAsync();
        }
        public static Task<Result[]> GroupByAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, object>> group, Expression<Func<T, bool>> having, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.Where(filter).GroupBy(group).Having(having).Select(selector).ToArrayAsync();
        }
        public static Task<Result[]> GroupByAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, object>> group, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.Where(filter).GroupBy(group).Select(selector).ToArrayAsync();
        }
        public static Task<Result[]> GroupByAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, object>> group, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.GroupBy(group).Select(selector).ToArrayAsync();
        }
        public static Task<Tuple<Result[], int>> GroupByQueryAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, object>> group, Expression<Func<T, Result>> selector, IBasicPage pager ) where T : class, new()
        {
            return Task.Factory.StartNew(() =>
            {
                Result[] list = repository.GroupByQuery(filter, group, selector, pager, out int count);
                return new Tuple<Result[], int>(list, count);
            });
        }


        public static Task<int> InsertAsync<T> ( this IRepository repository, T[] items ) where T : class, new()
        {
            IInsertable<T> insert = repository.Provider.Insertable(items);
            if ( items.Length < 500 )
            {
                return insert.UseParameter().ExecuteCommandAsync();
            }
            return insert.ExecuteCommandAsync();
        }
        public static Task<int> InsertAsync<T> ( this IRepository repository, T item ) where T : class, new()
        {
            return repository.Provider.Insertable(item).ExecuteCommandAsync();
        }
        public static Task<int> InsertAsync<T> ( this IRepository repository, List<T> items, Expression<Func<T, object>> filter ) where T : class, new()
        {
            StorageableResult<T> table = repository.Provider.Storageable(items).WhereColumns(filter).ToStorage();
            return table.AsInsertable.ExecuteCommandAsync();
        }

        public static Task<long> InsertReutrnIdentityAsync<T> ( this IRepository repository, T item ) where T : class, new()
        {
            return repository.Provider.Insertable(item).ExecuteReturnBigIdentityAsync();
        }
        public static Task<int> InsertTableAsync<T> ( this IRepository repository, List<T> items ) where T : class, new()
        {
            return repository.Provider.Fastest<T>().BulkCopyAsync(items);
        }

        public static Task<bool> IsExistAsync<T> ( this IRepository<T> repository, Expression<Func<T, bool>> filter ) where T : class, new()
        {
            return repository.Queryable.Where(filter).AnyAsync();
        }
        public static Task<bool> IsExistAsync<T> ( this IRepository<T> repository ) where T : class, new()
        {
            return repository.Queryable.AnyAsync();
        }
        public static Task<Result[]> JoinAsync<T, TInner, Result> ( this IRepository<T> repository, Expression<Func<T, TInner, bool>> joinExpression, Expression<Func<T, TInner, Result>> selector ) where T : class, new() where TInner : class
        {
            return repository.Queryable.InnerJoin(joinExpression).Select(selector).ToArrayAsync();
        }

        public static Task<Result[]> JoinAsync<T, TInner, Result> ( this IRepository<T> repository, Expression<Func<T, TInner, bool>> joinExpression, Expression<Func<T, TInner, bool>> filter, Expression<Func<T, TInner, Result>> selector ) where T : class, new() where TInner : class
        {
            return repository.Queryable.InnerJoin(joinExpression).Where(filter).Select(selector).ToArrayAsync();
        }
        public static Task<Result> JoinGetAsync<T, TInner, Result> ( this IRepository<T> repository, Expression<Func<T, TInner, bool>> joinExpression, Expression<Func<T, TInner, bool>> filter, Expression<Func<T, TInner, Result>> selector ) where T : class, new() where TInner : class
        {
            return repository.Queryable.InnerJoin(joinExpression).Where(filter).Select(selector).FirstAsync();
        }
        public static Task<Result> JoinGetAsync<T, TInner, Result> ( this IRepository<T> repository, Expression<Func<T, TInner, bool>> joinExpression, Expression<Func<T, TInner, Result>> selector ) where T : class, new() where TInner : class
        {
            return repository.Queryable.InnerJoin(joinExpression).Select(selector).FirstAsync();
        }
        public static Task<Result[]> JoinGroupByAsync<T, TInner, Result> ( this IRepository<T> repository,
            Expression<Func<T, TInner, bool>> joinExpression,
            Expression<Func<T, TInner, bool>> filter,
            Expression<Func<T, TInner, object>> group,
            Expression<Func<T, TInner, Result>> selector ) where T : class, new() where TInner : class
        {
            return repository.Queryable.InnerJoin(joinExpression).Where(filter).GroupBy(group).Select(selector).ToArrayAsync();
        }
        public static Task<Result[]> JoinGroupByAsync<T, TInner, Result> ( this IRepository<T> repository,
            Expression<Func<T, TInner, bool>> joinExpression,
              Expression<Func<T, TInner, object>> group,
            Expression<Func<T, TInner, Result>> selector ) where T : class, new() where TInner : class
        {
            return repository.Queryable.InnerJoin(joinExpression).GroupBy(group).Select(selector).ToArrayAsync();
        }
        public static Task<Tuple<Result[], int>> JoinQueryAsync<T, TInner, Result> ( this IRepository<T> repository,
            Expression<Func<T, TInner, bool>> joinExpression,
            Expression<Func<T, TInner, bool>> filter,
            Expression<Func<T, TInner, Result>> selector,
            IBasicPage pager ) where T : class, new() where TInner : class
        {
            return Task.Factory.StartNew(() =>
            {
                Result[] list = repository.JoinQuery(joinExpression, filter, selector, pager, out int count);
                return new Tuple<Result[], int>(list, count);
            });
        }
        public static Task<Tuple<Result[], int>> JoinQueryAsync<T, TInner, Result> ( this IRepository<T> repository,
            Expression<Func<T, TInner, bool>> joinExpression,
            Expression<Func<T, TInner, bool>> filter,
            Expression<Func<T, TInner, Result>> selector,
           int index,
           int size,
           Expression<Func<T, TInner, object>> orderby,
           OrderByType byType ) where T : class, new() where TInner : class
        {
            return Task.Factory.StartNew(() =>
            {
                Result[] list = repository.JoinQuery(joinExpression, filter, selector, index, size, orderby, byType, out int count);
                return new Tuple<Result[], int>(list, count);
            });
        }
        public static Task<Tuple<Result[], int>> JoinQueryAsync<T, TInner, Result> ( this IRepository<T> repository,
           Expression<Func<T, TInner, bool>> joinExpression,
           Expression<Func<T, TInner, Result>> selector,
           IBasicPage pager ) where T : class, new() where TInner : class
        {
            return Task.Factory.StartNew(() =>
            {
                Result[] list = repository.JoinQuery(joinExpression, selector, pager, out int count);
                return new Tuple<Result[], int>(list, count);
            });
        }

        public static Task<Result> MaxAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.MaxAsync(selector);
        }
        public static Task<Result> MaxAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.Where(filter).MaxAsync(selector);
        }
        public static Task<Result> MinAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.MinAsync(selector);
        }
        public static Task<Result> MinAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.Where(filter).MinAsync(selector);
        }
        public static Task<Tuple<T[], int>> QueryAsync<T> ( this IRepository<T> repository,
        Expression<Func<T, bool>> filter,
        IBasicPage pager ) where T : class, new()
        {
            return Task.Factory.StartNew(() =>
            {
                T[] list = repository.Query(filter, pager, out int count);
                return new Tuple<T[], int>(list, count);
            });
        }
        public static Task<Tuple<T[], int>> QueryAsync<T, Result> ( this IRepository<T> repository,
       IBasicPage pager ) where T : class, new()
        {
            return Task.Factory.StartNew(() =>
            {
                T[] list = repository.Query(pager, out int count);
                return new Tuple<T[], int>(list, count);
            });
        }
        public static Task<Tuple<Result[], int>> QueryAsync<T, Result> ( this IRepository<T> repository,
      Expression<Func<T, bool>> filter,
      Expression<Func<T, Result>> selector,
      IBasicPage pager ) where T : class, new()
        {
            return Task.Factory.StartNew(() =>
            {
                Result[] list = repository.Query(filter, selector, pager, out int count);
                return new Tuple<Result[], int>(list, count);
            });
        }
        public static Task<Tuple<Result[], int>> QueryAsync<T, Result> ( this IRepository<T> repository,
     Expression<Func<T, bool>> filter,
     IBasicPage pager ) where T : class, new() where Result : class
        {
            return Task.Factory.StartNew(() =>
            {
                Result[] list = repository.Query<Result>(filter, pager, out int count);
                return new Tuple<Result[], int>(list, count);
            });
        }
        public static Task<Result> SumAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.SumAsync(selector);
        }
        public static Task<Result> SumAsync<T, Result> ( this IRepository<T> repository, Expression<Func<T, bool>> filter, Expression<Func<T, Result>> selector ) where T : class, new()
        {
            return repository.Queryable.Where(filter).SumAsync(selector);
        }

        public static Task<bool> UpdateAsync<T, Result> ( this IRepository repository, T data, string[] setColumn ) where T : class, new()
        {
            if ( setColumn.IsNull() )
            {
                return repository.Provider.Updateable(data).ExecuteCommandHasChangeAsync();
            }
            return repository.Provider.Updateable(data).UpdateColumns(setColumn).ExecuteCommandHasChangeAsync();
        }

        public static Task<bool> UpdateAsync<T, Result> ( this IRepository repository, T data, string[] setColumn, Expression<Func<T, bool>> filter ) where T : class, new()
        {
            if ( setColumn.IsNull() )
            {
                return repository.Provider.Updateable(data).Where(filter).ExecuteCommandHasChangeAsync();
            }
            return repository.Provider.Updateable(data).Where(filter).UpdateColumns(setColumn).ExecuteCommandHasChangeAsync();
        }

        public static Task<bool> UpdateAsync<T, Result> ( this IRepository repository, T[] data, string[] setColumn ) where T : class, new()
        {
            if ( setColumn.IsNull() )
            {
                return repository.Provider.Updateable(data).ExecuteCommandHasChangeAsync();
            }
            return repository.Provider.Updateable(data).UpdateColumns(setColumn).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> UpdateAsync<T, Result> ( this IRepository repository, string table, T[] data, string[] setColumn ) where T : class, new()
        {
            if ( setColumn.IsNull() )
            {
                return repository.Provider.Updateable(data).AS(table).ExecuteCommandHasChangeAsync();
            }
            return repository.Provider.Updateable(data).AS(table).UpdateColumns(setColumn).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> UpdateAsync<T> ( this IRepository repository, Expression<Func<T, bool>> columns, Expression<Func<T, bool>> filter ) where T : class, new()
        {
            return repository.Provider.Updateable<T>().SetColumns(columns).Where(filter).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> UpdateAsync<T, Set> ( this IRepository repository, Set set, Expression<Func<T, bool>> filter ) where T : class, new()
        {
            return repository.Provider.Updateable<T>(set).Where(filter).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> UpdateAsync<T, Set> ( this IRepository repository, Set set, Expression<Func<T, object>> whereCols ) where T : class, new()
        {
            return repository.Provider.Updateable<T>(set).WhereColumns(whereCols).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> UpdateAsync<T, Set> ( this IRepository repository, Set set, string[] whereCols ) where T : class, new() where Set : class
        {
            return repository.Provider.Updateable<T>(set).WhereColumns(whereCols).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> UpdateAsync<T, Set> ( this IRepository repository, Set[] set ) where T : class, new() where Set : class
        {
            T[] datas = set.ToConvertAll<Set, T>(out string[] column);
            return repository.Provider.Updateable(datas).UpdateColumns(column).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> UpdateAsync<T> ( this IRepository repository, T[] datas, Expression<Func<T, object>> whereCols ) where T : class, new()
        {
            return repository.Provider.Updateable(datas).WhereColumns(whereCols).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> UpdateAsync<T> ( this IRepository repository, Expression<Func<T, T>> columns, Expression<Func<T, bool>> filter ) where T : class, new()
        {
            return repository.Provider.Updateable<T>().Where(filter).SetColumns(columns).ExecuteCommandHasChangeAsync();
        }

        public static Task<bool> UpdateAsync<T> ( this IRepository repository, Expression<Func<T, T>> columns, string[] whereCols ) where T : class, new()
        {
            return repository.Provider.Updateable<T>().WhereColumns(whereCols).SetColumns(columns).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> UpdateAsync<T> ( this IRepository repository, Expression<Func<T, T>> columns, Expression<Func<T, object>> whereCols ) where T : class, new()
        {
            return repository.Provider.Updateable<T>().WhereColumns(whereCols).SetColumns(columns).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> UpdateAsync<T> ( this IRepository repository, T source, string[] setCols ) where T : class, new()
        {
            return repository.Provider.Updateable(source).UpdateColumns(setCols).ExecuteCommandHasChangeAsync();
        }
        public static Task<bool> UpdateAsync<T> ( this IRepository repository, T source, T set ) where T : class, new()
        {
            string[] cols = source.Merge<T>(set);
            if ( cols.Length == 0 )
            {
                return Task.FromResult(false);
            }
            return repository.UpdateAsync(source, cols);
        }
        public static Task<bool> UpdateAsync<T, Set> ( this IRepository repository, T source, Set set ) where T : class, new() where Set : class
        {
            string[] cols = source.Merge(set);
            if ( cols.Length == 0 )
            {
                return Task.FromResult(false);
            }
            return repository.UpdateAsync(source, cols);
        }
        public static Task<int> UpdateRetrunRowNumAsync<T> ( this IRepository repository, Expression<Func<T, T>> columns, Expression<Func<T, bool>> filter ) where T : class, new()
        {
            return repository.Provider.Updateable<T>().Where(filter).SetColumns(columns).ExecuteCommandAsync();
        }
        public static Task<bool> UpdateOnlyAsync<T> ( this IRepository repository, T[] datas, Expression<Func<T, object>> setCol ) where T : class, new()
        {
            return repository.Provider.Updateable(datas).UpdateColumns(setCol).ExecuteCommandHasChangeAsync();
        }
    }
}
